proc set_option {} {
        global info runstate LOG_SEV LOG_SEV1 exp_log RUN_TEST_STATE RETRY_TIMES_WHEN_FAIL exit_when_test_fail exit_when_found_problem
        set w .set_option
        catch {destroy $w}
        toplevel $w
        wm title $w "Input/Change option"
        wm iconname $w "iconname?"
        positionWindow $w
	frame $w.content
        set left_con [frame $w.content.left]
        set right_con [frame $w.content.right]
        frame $w.command
	pack $w.content -side top -fill x -pady 2m
        pack $left_con $right_con -side left -expand yes -padx 10 -pady 10 -fill both
        pack $w.command -side bottom  -fill x -pady 2m

        label $left_con.log_sev -text "Log Severity(1-7)" -padx 0 -width 40 -anchor w
        label $left_con.retry -text "Retry times when test fail" -padx 0 -width 40 -anchor w
        label $left_con.timeout -text "Timeout for command running" -padx 0 -width 40 -anchor w
        label $left_con.sleep_after_conf -text "Sleep seconds after finishing config" -padx 0 -width 40 -anchor w
        label $left_con.refresh_db_timer -text "Sleep seconds to refresh database connection" -padx 0 -width 40 -anchor w

        label $left_con.command_check_version -text "Command to check switch version" -padx 0 -width 40 -anchor w
        label $left_con.command_check_version2 -text "Command_2 to check switch version" -padx 0 -width 40 -anchor w
        label $left_con.command_check_crash -text "Command to check crash" -padx 0 -width 40 -anchor w
        entry $right_con.log_sev -width 2 -relief sunken -textvariable LOG_SEV
        entry $right_con.retry -width 2 -relief sunken -textvariable RETRY_TIMES_WHEN_FAIL
        entry $right_con.timeout -width 2 -relief sunken -textvariable TIMEOUT
        entry $right_con.sleep_after_conf -width 2 -relief sunken -textvariable SLEEP_AFTER_CONF
        entry $right_con.refresh_db_timer -width 4 -relief sunken -textvariable DB_KEEPALIVE_TIMER

        entry $right_con.command_check_version -width 40 -relief sunken -textvariable cmd_check_sw_version
        entry $right_con.command_check_version2 -width 40 -relief sunken -textvariable cmd_check_sw_version2
        entry $right_con.command_check_crash -width 40 -relief sunken -textvariable cmd_check_crash
	pack $left_con.log_sev $left_con.retry $left_con.timeout $left_con.sleep_after_conf $left_con.refresh_db_timer $left_con.command_check_version $left_con.command_check_version2 $left_con.command_check_crash -side top
	pack $right_con.log_sev $right_con.retry $right_con.timeout $right_con.sleep_after_conf $right_con.refresh_db_timer $right_con.command_check_version $right_con.command_check_version2 $right_con.command_check_crash -side top
	checkbutton $w.command.exp_log -variable exp_log -text "exp_internal log"  -anchor w
	checkbutton $w.command.exit_problem -variable exit_when_found_problem -text "exit when found problem"  -anchor w
	checkbutton $w.command.exit_fail -variable exit_when_test_fail -text "exit when test fail"  -anchor w


        for {set i 0} {$i<10} {incr i +1} {
		if {[string last "$i;" $RUN_TEST_STATE] != -1} {
                	set runstate($i) 1
                	log_info $info "current runstate($i): $runstate($i)" 5
		}
        }

	set run_state [frame $w.command.runstate]
	pack $run_state -side top -fill x -pady 2m
	label $run_state.desc -text "select test state to run:" -padx 0 -width 15 -anchor w
	checkbutton $run_state.state0 -variable runstate(0) -text "0:general1"  -anchor w
	checkbutton $run_state.state1 -variable runstate(1) -text "1:general2"  -anchor w
	checkbutton $run_state.state2 -variable runstate(2) -text "2:general3"  -anchor w
	checkbutton $run_state.state3 -variable runstate(3) -text "3:undefined"  -anchor w
	checkbutton $run_state.state4 -variable runstate(4) -text "4:undefined"  -anchor w
	checkbutton $run_state.state5 -variable runstate(5) -text "5:Voice H323"  -anchor w
	checkbutton $run_state.state6 -variable runstate(6) -text "6:Voice SIP"  -anchor w
	checkbutton $run_state.state7 -variable runstate(7) -text "7:HA"  -anchor w
	checkbutton $run_state.state8 -variable runstate(8) -text "8:IPSec"  -anchor w
	checkbutton $run_state.state9 -variable runstate(9) -text "9:suspend"  -anchor w
	pack $run_state.desc -side top -fill x
	for {set i 0} {$i < 10} {incr i +1} {
		pack $run_state.state$i -side top -fill x
	}
	

        button $w.command.confirm -text Confirm -command "set_runstate ; catch {destroy $w}; set_exp_internal; return 1 "
        button $w.command.cancel -text Cancel -command " catch {destroy $w} ; return 0 "
        pack $w.command.exp_log $w.command.exit_problem $w.command.exit_fail -side top -expand 1 -anchor w
        pack $w.command.confirm $w.command.cancel -side left -expand 1
}

proc set_db_conn {} {
#For setting up database connection options	
}

proc set_options {} {
#For setting up various options which were saved in options table
	global info db_handle
}
proc set_runstate {} {
	global RUN_TEST_STATE runstate info exp_log exit_when_test_fail exit_when_found_problem
	set RUN_TEST_STATE ""
	for {set i 0} {$i<10} {incr i +1} {
		log_info $info "runstate($i): $runstate($i)" 2
		if {$runstate($i) == 1} {
			append RUN_TEST_STATE $i
			append RUN_TEST_STATE ";"
		}
	}
	log_info $info "RUN_TEST_STATE: $RUN_TEST_STATE" 2
        log_info $info "exp_log: $exp_log; exit_when_test_fail: $exit_when_test_fail; exit_when_found_problem: $exit_when_found_problem" 2
}
proc set_exp_internal {} {
	global info exp_log
	exp_internal $exp_log; 
	log_info $info "set exp_internal to $exp_log" 4
}

proc exit_from_dev {port mode spawn_id_value} {
	global SYS_PROMPT info interrupt
	log_info $info "port: $port; mode: $mode; spawn_id_value: $spawn_id_value" 5
if {$interrupt==0} {
	if {[catch {exp_send -i $spawn_id_value "try if it is still alive\r"} errinfo]!=0} {
#that means the spawn_id already ended.
		log_info $info "spawn_id $spawn_id_value already exited, don't need exit it manually" 4	
		log_info $info "error info: $errinfo" 5	
		return 1
	}
	if {$spawn_id_value==0} {
		log_info $info "spawn_id value is 0,don't need exit it manually" 4
		return 1
	}
        expect_after {
	        -i $spawn_id_value eof {
             		log_info $info "expect_process exit unexpectly" 1
                	return 2
        	}
        }
	if {$port != 23 && $mode == "telnet"} {
        	exp_send -i $spawn_id_value "\x1D"
	        expect -i $spawn_id_value -re "telnet>|Telnet>"
        	exp_send -i $spawn_id_value "quit\r"
	        expect  { 
			-i $spawn_id_value -re "closed" {catch {close -i $spawn_id_value}; wait -i $spawn_id_value; return 1}
#			-re eof {close -i $spawn_id_value; wait -i $spawn_id_value; return 1}
#close and wait commands are used for close the spawn process clearly, then it won't left a defunct process in system
		}
	} else {
#		exp_send -i $spawn_id_value "\x03"
#		expect -i $spawn_id_value -re $SYS_PROMPT
		if {[string tolower $mode]=="minicom"} {
			exp_send -i $spawn_id_value -raw "\x01"
			exp_send -i $spawn_id_value "q"
			exp_send -i $spawn_id_value "\r"
			sleep 1
#			expect -i $spawn_id_value eof 
			catch {exp_close -i $spawn_id_value};
			exp_wait -i $spawn_id_value;
			return 1
		} else {
           		expect_after {
		                -i $spawn_id_value eof {
                		        log_info $info "expect_process exit unexpectly" 4
                        		return 2
				}
			}
# \x03 is for telnet to linux host and running a process which cannot exit to prompt by itself. but for Telnet to fortigate, \x03 will cause telnet session closed immediately. So I just put "\x03" and "exit" together and input them one time,should be able to adapt for the two cases
#May 11,2006 Run test 2611_ping_VIPgrp failed sometimes, then add this sleep command
# because of speed problem. change "sleep 1" to "sleep 0.1" in Jan 30,2007 
                        sleep 0.1
#	        	exp_send -i $spawn_id_value "\x03\r exit \r"
#add more Ctrl_C is for the case in which we need more Ctrl_C to exit
	        	exp_send -i $spawn_id_value "\x03\r\x03\r\x03\r exit \r"
		        expect {
				-i $spawn_id_value -re "closed|logout|lost"  { 
#It's very strange, changing "close" to "exp_close" maybe hang the PC. 
					catch {close -i $spawn_id_value}; 
					catch {wait -i $spawn_id_value}; 
					return 1;}
				-i $spawn_id_value -re "\\$" { 
					exp_send -i $spawn_id_value "exit \n\r"; 
					expect -i $spawn_id_value -re "closed|logout|lost"; 
#change exp_close to close. suspect the connection was not disconnected properly. May 16,2008
					catch {close -i $spawn_id_value};
					catch {wait -i $spawn_id_value}; 
					log_info $info "Finished exit. port: $port; mode: $mode; spawn_id_value: $spawn_id_value" 4
					return 1
				}
                                -i $spawn_id_value -re " >" {
                                        exp_send -i $spawn_id_value "quit \n\r";
                                        exp_send -i $spawn_id_value "n\n\r";
                                        expect -i $spawn_id_value -re "closed|logout|lost";
#change exp_close to close. suspect the connection was not disconnected properly. May 16,2008
                                        catch {close -i $spawn_id_value};
                                        catch {wait -i $spawn_id_value};
                                        log_info $info "Finished exit. port: $port; mode: $mode; spawn_id_value: $spawn_id_value" 4
                                        return 1
                                }
			}
		}
	}
} else {
	log_info $info "system running interrupted, don't need exit manually" 2
}
}

proc get_access {host host_ip acc_mode acc_user acc_pass acc_port} {
	global db_prv_handle DEV_TB info DB_PRV_NAME
	upvar $host_ip host_ip1 $acc_mode acc_mode1 $acc_user acc_user1 $acc_pass acc_pass1 $acc_port acc_port1
	set sql_qur "SELECT * FROM $DEV_TB where name='$host'"
        set sky_response [mysql_pack $sql_qur $DB_PRV_NAME ]
        set parent_line [lindex $sky_response 0]
        set sql_ret_str [lindex $sky_response 1]

        set k 0

        if {$parent_line >"0"} {
		log_info $info "Good, Found $parent_line device records in table $DEV_TB! " 4
		set cur_row [lindex $sql_ret_str 0]
		set host_ip1 [lindex $cur_row 3]
		set acc_mode1 [lindex $cur_row 4]
		set acc_user1 [lindex $cur_row 5]
		set acc_pass1 [lindex $cur_row 6]
		set acc_port1 [lindex $cur_row 7]
		log_info $info "ip:$host_ip1 mode:$acc_mode1 user:$acc_user1 pass:$acc_pass1 port:$acc_port1" 6
		return 1
	} else {
		log_info $info "Cannot find device $host in DB! program exited" 1
		return 0
	}
}

proc pingtest {ping_des} {
	exp_send "\r"
	expect {
		-re "\\>" {puts "This is windows pc\n"; set ping_cmd "ping $ping_des -n 1 \n\r"}
		-re "\\$|\#" {puts "This is linux or unix\n"; set ping_cmd "ping $ping_des -c 1 \r"}
		timeout {puts "Don't know which OS it is"; set ping_cmd "ping $ping_des \r"}
	}
	set exp_res "from $ping_des"
	set lose 0
	for {set i 1} {$i<=10} {incr i +1} {
		if {[run_comm_exp_res $ping_cmd $exp_res]==0} {
			puts "lost one packet , i= $i"
			incr lose +1
		} else {
			puts "reply successfully, i=$i"
		}
	}
	if {$lose <= 2} {
		return 1
	} else {
		return 0
	}
}

proc exit_from_specified_dev {dev exit_spawn_id} {
        global info
	if {[string trim $dev]==""} {
		log_info $info "Device name is blank, donot need exit. from proc 'exit_from_specified_dev' " 4
		return 0
	}
	set nouse ""
        map_dev_cmd dev nouse
        if {[get_access $dev src_ip src_mode src_user src_pass src_port]==0} {
		log_info $info "Cannot get access from dev_access table for device $dev, donot need exit. from proc 'exit_from_specified_dev' " 4
                return 0
        }
	exit_from_dev $src_port $src_mode $exit_spawn_id
}
proc map_dev_cmd {dev1 cmd1} {
	global info comm_array map1 map_other change_dut1
	upvar $dev1 dev $cmd1 cmd
        #check if we need to change DUT
        set dev [string tolower [string trim $dev]]
	set dev_changed 1
	set other_changed 1
	log_info $info "do we need this loop? for $dev" 5
###	sleep 5
	while {$dev_changed == 1 || $other_changed == 1 } {
		log_info $info "if we see this line more than one times, then we need this loop. for $dev" 5
###	sleep 5
		set other_changed 0
                #check if we need to change Test_support devices
                set ii 1
                while {[info exists map_other($ii,1,1)] && $change_dut1==1} {
                        log_info $info "dev: $dev; map_other($ii,1,1): $map_other($ii,1,1)  -> $map_other($ii,1,2)" 5
                        if {[string trim $dev] == [string trim $map_other($ii,1,1)]} {
                                ###in case override previous mapping, mapping device only when device name changed
                                ###Case: 1st mapping: DUT1(test_p2)->FG400(p2_v2), 2nd mapping: DUT1(phase1)->DUT1(phase1-interface)
                                if {$map_other($ii,1,1)!=$map_other($ii,1,2)} {
					set host $map_other($ii,1,2)
	                                set cmd [chg_string_by_map_other $ii map_other $cmd]
        	                        log_info $info "change config for $dev, dev_name was also changed" 4
        				set other_changed 1
				} else {
                                	if {![info exists host]} {set host $map_other($ii,1,1)}
	                                set cmd [chg_string_by_map_other $ii map_other $cmd]
        	                        log_info $info "change config for $dev, dev_name was not changed" 4
        				###set other_changed 1
				}
        		}
                        incr ii +1
                }
                #check if we need to change DUT devices
		set dev_changed 0
                if {$dev == $map1(1,1) && $change_dut1==1} {
                        ###in case override previous mapping, mapping device only when device name changed
                        ###Case: 1st mapping: DUT1(test_p2)->FG400(p2_v2), 2nd mapping: DUT1(phase1)->DUT1(phase1-interface)
                        if {$map1(1,1)!=$map1(1,2)} {set host $map1(1,2)}
                        if {![info exists host]} {set host $map1(1,1)}
                        set cmd [chg_string_by_map map1 $cmd]
                        set dev_changed 1
                } else {
                        if {![info exists host]} {set host $dev}
                }
        	set dev $host
	}
}
proc get_sw_version {sw_name} {
	#This proc is used to get switch software version : IOS or CatOS
	global info sw_version cmd_check_sw_version cmd_check_sw_version2
	#check if we have cached sw_version
	set i 1
        while {[info exists sw_version($i,1)]} {
		if {$sw_version($i,1) == $sw_name} {
			return $sw_version($i,2)
		}
		incr i +1
	}
	#probe switch to get the version	
        if {[run_comm_on_dev $sw_name $cmd_check_sw_version 1]!=0} {
                log_info $info "$sw_name is IOS" 2
		set sw_version($i,1) $sw_name
		set sw_version($i,2) "ios"
        } else {
		if {[run_comm_on_dev $sw_name $cmd_check_sw_version2 1]!=0} {
			log_info $info "$sw_name is FortiSwitch" 2
			set sw_version($i,1) $sw_name
			set sw_version($i,2) "fsw"
		} else {
	                log_info $info "$sw_name is not IOS or FortiSwitch, suppose it is CatOS" 2
			set sw_version($i,1) $sw_name
			set sw_version($i,2) "catos"
		}
        }
	return $sw_version($i,2)
}
proc set_switch {sw_cmd} {
	global info comm_array db_prv_handle SW_DEV_CONN DB_PRV_NAME
	set sw_cmd_array(1) ""
	log_info $info "before chg, sw_cmd_array(1): $sw_cmd_array(1)" 6
        ch_string_to_array_new $sw_cmd sw_cmd_array
	log_info $info "after chg, sw_cmd_array(1): $sw_cmd_array(1)" 6
        for {set i 0} {$i >= 0} {incr i +1} {
		#check command exists, if not, return
                if {[info exists sw_cmd_array($i)]==0} {return 1}
                log_info $info "i: $i; run command($i):$sw_cmd_array($i)" 4
		set sw_cmd [string trim $sw_cmd_array($i)]
		if {$sw_cmd == ""} continue
		set sw_cmd_real ""
		if {[string range [string trimleft $sw_cmd] 0 2] != "###"} {
		    if {[regexp {set_sw_port\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(.*)} $sw_cmd no_use dev_name dev_port link mode vlan_str]==1} {
			log_info $info "dev_name: $dev_name; dev_port:$dev_port; link:$link; mode:$mode; vlan_str:$vlan_str" 4
			set old_dev_name $dev_name
                        #check if we need to change DUT
                        map_dev_cmd dev_name dev_port
			set dev_name $old_dev_name
                        map_dev_cmd dev_name vlan_str
                        log_info $info "after substitute. dev_name: $dev_name; dev_port: $dev_port; vlan_str: $vlan_str" 4
			#remove postfix _console to make it searchable in sw_dev_conn table
			set dev_name [trimend [string tolower $dev_name] "_console"]
                        log_info $info "after remove _console. dev_name: $dev_name; dev_port: $dev_port" 4
			

		        set sql_qur "SELECT sw_name,sw_port,status from $SW_DEV_CONN where dev_name='$dev_name' and dev_port='$dev_port'"
                        set sky_response [mysql_pack $sql_qur $DB_PRV_NAME ]
                        set infect_lines [lindex $sky_response 0]
                        set sql_ret_str [lindex $sky_response 1]
 
                        set k 0

			log_info $info "sql_stat: $sql_qur" 5
		        if {$infect_lines >"0"} {
				if {$infect_lines > "1"} {
					log_info $info "Warning: there are more than 1 line for dev_name='$dev_name' and dev_port='$dev_port' in table $SW_DEV_CONN, use first one" 2
				} 
				set cur_row [lindex $sql_ret_str 0]
                        	set sw_name [lindex $cur_row 0]
                        	set sw_port [lindex $cur_row 1]
                        	set status [lindex $cur_row 2]
            			set sw_version [get_sw_version $sw_name]
				#set sw_version "catos"
				switch $sw_version {
				catos {
					if {[string tolower $mode]=="trunk"} {
						#First we set it to vlan 1, that can set native vlan to vlan 1
						append sw_cmd_real "set vlan 1 $sw_port\n"
						append sw_cmd_real "set trunk $sw_port off\n"
						#4006 switch has bug when setting up trunk. add below sleep command to workarond it
						append sw_cmd_real "sleep_test 3\n"
						append sw_cmd_real "set trunk $sw_port on\n"
						append sw_cmd_real "clear trunk $sw_port 1-1005,1025-4094\n"
						append sw_cmd_real "set trunk $sw_port $vlan_str\n"
					} elseif {[string tolower $mode]=="access"} {
						append sw_cmd_real "set trunk $sw_port off\n"
						append sw_cmd_real "set vlan $vlan_str $sw_port\n"
					}
					if {[string tolower $link] =="up"} {
						append sw_cmd_real "set port enable $sw_port\n"
					} elseif {[string tolower $link] =="down"} {
						append sw_cmd_real "set port disable $sw_port\n"
					}
				}
				fsw {
                                        append sw_cmd_real "config \n"
                                        append sw_cmd_real "interface $sw_port\n"
                                        if {[string tolower $mode]=="trunk"} {
                                                append sw_cmd_real "switchport allowed vlan add tagged $vlan_str\n"
                                                append sw_cmd_real "switchport tagging $vlan_str\n"
                                                append sw_cmd_real "switchport native vlan 1\n"
                                        } elseif {[string tolower $mode]=="access"} {
                                                append sw_cmd_real "switchport allowed vlan add untagged $vlan_str\n"
                                                append sw_cmd_real "switchport native vlan $vlan_str\n"
                                        }
                                        if {[string tolower $link] =="up"} {
                                                append sw_cmd_real "no shutdown\n"
                                        } elseif {[string tolower $link] =="down"} {
                                                append sw_cmd_real "shutdown\n"
                                        }
                                        append sw_cmd_real "end\n"
				}
				ios {
					append sw_cmd_real "config ter\n"
					append sw_cmd_real "interface $sw_port\n"
                                        if {[string tolower $mode]=="trunk"} {
                                                append sw_cmd_real "switchport trunk encapsulation dot1q\n"
                                                append sw_cmd_real "switchport mode trunk\n"
                                                append sw_cmd_real "switchport trunk native vlan 1\n"
                                                append sw_cmd_real "switchport trunk allowed vlan none\n"
                                                append sw_cmd_real "switchport trunk allowed vlan add $vlan_str\n"
                                        } elseif {[string tolower $mode]=="access"} {
                                                append sw_cmd_real "switchport mode access\n"
                                                append sw_cmd_real "switchport access vlan $vlan_str\n"
                                        }
                                        if {[string tolower $link] =="up"} {
                                                append sw_cmd_real "no shutdown\n"
                                        } elseif {[string tolower $link] =="down"} {
                                                append sw_cmd_real "shutdown\n"
                                        }
					append sw_cmd_real "end\n"
				}
				}
				log_info $info "sw_cmd: $sw_cmd;sw_name:$sw_name;sw_port:$sw_port" 5
				log_info $info "dev_name: $dev_name;dev_port:$dev_port;link:$link;mode:$mode;vlan_str:$vlan_str" 5
				log_info $info "sw_cmd_real: $sw_cmd_real" 5
				if {[run_comm_on_dev $sw_name $sw_cmd_real 1] != 0} {
					log_info $info "Succeed to run sw_cmd:$sw_cmd" 4
				} else {
					log_info $info "Fail to run sw_cmd:$sw_cmd" 2
 				}
			} else {
				log_info $info "Warning: Can not find record for dev_name='$dev_name' and dev_port='$dev_port' in table $SW_DEV_CONN, ignore this set_sw command" 2
			}
		    } else {
			log_info $info "Warning: Cannot parse set_sw command!" 2
			log_info $info "set_sw cmd: $sw_cmd!" 2
		    }
		} else {
			log_info $info "comment out: $sw_cmd" 2
		}
	}
}
proc run_comm_on_dev {dev cmd exit_process} {
#return 0 means fail, otherwise it is spawn_id and not fail. ***it should not return 1	in any case
#also, connection should already be disconnected except exit_process is 0	
	global info comm_array map1 map_other change_dut1
        if {[string tolower [string range [string trim $dev] 0 9]] == "switch_cmd"} {
		#handle special switch config command
		if {[set_switch $cmd] == 1} {
			log_info $info "Succeed to set switch" 4
			return 1
		} else {
			log_info $info "Fail to set switch" 2
			return 0
		}
	}

        #check if we need to change DUT
	log_info $info "before substitute. dev: $dev; cmd: $cmd" 4
	map_dev_cmd dev cmd
	log_info $info "after substitute. dev: $dev; cmd: $cmd" 4

	if {[get_access $dev src_ip src_mode src_user src_pass src_port]==0} {
		return 0
        }
	#run cmd in dev
       ch_string_to_array $cmd 
       if {[set spawn_id_process [access_host_port $src_ip $src_mode $src_user $src_pass $src_port [array get comm_array] $exit_process]]!=0} {
		return $spawn_id_process
       } else {
		return 0
       }
}
proc kill_line_in_terminal_server {server_ip port} {
	global info SYS_RUN_PROMPT spawn_id 
	if {[set connect [connect_setup $server_ip "cisco" "cisco" "telnet" "23"]]!=0} {
		set line [incr port -2000]
		set cmd "clear line $line\r"
		log_info $info "clear line $line in terminal server $server_ip" 3
		run_comm_exp_res $cmd $SYS_RUN_PROMPT 0 $SYS_RUN_PROMPT
		exit_from_dev "23" "telnet" $spawn_id	
	} else {
		log_info $info "failed to clear line when trying to connect to terminal server:$server_ip" 2
	}
}
proc connect_setup {src_ip src_user src_pass src_mode src_port} {
	global info running_pid spawn_id interrupt
	set retry_num 3
	while {[set connect [Connect_port $src_ip $src_user $src_pass $src_mode $src_port]]!=1} {
		incr retry_num -1
                log_info $info "fail to connect to $src_ip, retry: $retry_num. Connect: $connect " 2
                if {$src_mode=="telnet" && $src_port==23 || $connect==2} {
                       log_info $info "don't need exit from telnet 23 session or failed minicom session" 3
#close and wait commands are used for close the spawn process clearly, then it won't left a defunct process in system
			catch {close};
			wait;
                } else {
                       log_info $info "exit from the fail session for minicom or terminal server" 3
                       exit_from_dev $src_port $src_mode $spawn_id
                }
		if {$interrupt == 1} {
			log_info $info "system interrrupted, exit from connect_setup" 2
			return 0
		}
                if {$retry_num == 0} {
                       log_info $info "Cannot connect to $src_ip, test failed" 3
                       return 0
                }
		if {$src_mode=="telnet" && $src_port!=23} {kill_line_in_terminal_server $src_ip $src_port}
		#because of speed, changing 2 seconds to 0.2 seconds.
                sleep 0.2
        }
	set wish_pid [pid]
	set current_pid [exp_pid]
	append running_pid "$current_pid;"
	log_info $info "spawn_id: $spawn_id; wish_pid: $wish_pid current pid is : $current_pid; running_pid: $running_pid" 4
	if {[string length $running_pid] > 6000} {
		set running_left [string range $running_pid 4990 end]
		set running_pid [string range $running_pid 0 4999]
		kill_running_pid
		set running_pid $running_left
	}
	return $spawn_id
}
proc submit_res_and_exit { i test_name test_pre_src spawn_id_pre_cmd test_src spawn_id_cmd test_post_src spawn_id_post_cmd} {
	global array_test info 
#Start to handle exit from each connection
	if {$spawn_id_pre_cmd!=0 && $test_pre_src!=""} {exit_from_specified_dev $test_pre_src $spawn_id_pre_cmd}
        if {$spawn_id_cmd!=0 && $test_src!=""} {exit_from_specified_dev $test_src $spawn_id_cmd}
        if {$spawn_id_post_cmd!=0 && $test_post_src!=""} {exit_from_specified_dev $test_post_src $spawn_id_post_cmd}
	if {$array_test($i,4)==1} {
	        log_info $info  "All right, test $test_name passed by itself!" 3
        	if {$array_test($i,5)==0} {
        		set array_test($i,6) 1
	                log_info $info "Good, that's what we expected in this env, test $test_name pass!" 3
        	} else {
                	set array_test($i,6) 0
	                log_info $info "Bad, that's not what we expected in this env, test $test_name failed!" 3
		}
	} else {
                log_info $info  "Bad, test $test_name failed by itself!" 3
                if {$array_test($i,5)==0} {
                        set array_test($i,6) 0
                        log_info $info "Bad, that's not what we expected in this env, test $test_name failed!" 3
                } else {
                        set array_test($i,6) 1
                        log_info $info "Good, that's what we expected in this env, test $test_name pass!" 3
                }
	}
	submit_res $i
}

proc exit_from_all_dev { sum} {
        global info spawn_id_array test_dev 
	for {set i 1} {$i<=$sum} {incr i +1} {
		#Start to handle exit from each connection
        	if {[info exists spawn_id_array($i)] && $spawn_id_array($i)!=0 && $test_dev($i)!=""} {exit_from_specified_dev $test_dev($i) $spawn_id_array($i)}
	}
	###In case some processes can not be exited successfully, run below proc to kill all current pid
	#kill_running_pid
}

proc submit_res_and_log { i } {
        global array_test info
        if {$array_test($i,4)==1} {
                log_info $info  "All right, test $array_test($i,1) passed by itself!" 2
                if {$array_test($i,5)==0} {
                        set array_test($i,6) 1
                        log_info $info "Good, that's what we expected in this env, test $array_test($i,1) pass!" 2
                } else {
                        set array_test($i,6) 0
                        log_info $info "Bad, that's not what we expected in this env, test $array_test($i,1) failed!" 2
                }
        } else {
                log_info $info  "Bad, test $array_test($i,1) failed by itself!" 2
                if {$array_test($i,5)==0} {
                        set array_test($i,6) 0
                        log_info $info "Bad, that's not what we expected in this env, test $array_test($i,1) failed!" 2
                } else {
                        set array_test($i,6) 1
                        log_info $info "Good, that's what we expected in this env, test $array_test($i,1) pass!" 2
                }
        }
        submit_res $i
	return $array_test($i,6)
}

proc submit_res {i} {
	global array_test operator info DB_PRV_NAME LOG_RESULT run_case_no parent_env_for_pkg 
        set array_test($i,8) $operator$run_case_no
	
        set array_test($i,9) "[clock format [clock second] -format "%Y %b %d %H:%M:%S"]"
	set total_env "$parent_env_for_pkg/$array_test($i,3)"
        set sql_qur "INSERT INTO $LOG_RESULT values('','$array_test($i,8)', '$array_test($i,9)','$array_test($i,1)', '$total_env','$array_test($i,4)', '$array_test($i,5)','$array_test($i,6)', '$array_test($i,7)')"
        set sky_response [mysql_pack $sql_qur $DB_PRV_NAME ]
        set infect_line [lindex $sky_response 0]
        set sql_ret_str [lindex $sky_response 1]

        set k 0

        if {$infect_line =="1"} {
		log_info $info "Save result to database. Insert Into database $LOG_RESULT successfully!" 4
	} else {
                log_info $info "Save result to database. Fail to insert into database !" 2
        }
}


proc process_cmd_on_dev {run_index order_no run_dev run_cmd_grp run_spawn_id_global run_exit run_negate run_new_conn run_prev_conn} {
	#return 1 means test failed, donot need to carry on remaining test
	#return 0 means test succeeded, need to carry on remaining test
	global info array_test get_special_exp interrupt test_dev spawn_id_array comm_array spawn_id
	upvar $run_spawn_id_global run_spawn_id
	log_info $info "run_index: $run_index; order_no:$order_no; run_dev:$run_dev; " 4
	log_info $info "run_spawn_id_global: $run_spawn_id_global; run_exit:$run_exit; run_negate:$run_negate; " 4
	log_info $info "run_new_conn: $run_new_conn; run_prev_conn:$run_prev_conn; " 4
	log_info $info "run_cmd_grp: $run_cmd_grp; " 6
	if {$run_cmd_grp!="" && $interrupt==0} {
		if {$run_new_conn==0} {
			log_info $info "Need to use old connection $run_prev_conn " 2
			
			if {[string toupper $test_dev($run_prev_conn)]==[string toupper $run_dev]} {
				#mapping cmd&dev
				map_dev_cmd run_dev run_cmd_grp

				set spawn_id $spawn_id_array($run_prev_conn)
				log_info $info "Setup current spawn_id to $spawn_id_array($run_prev_conn) " 2
                                ch_string_to_array $run_cmd_grp
                                set test_result [run_com_array_in_connection [array get comm_array]]
                                if {$test_result==0} {
                                        if {$get_special_exp==1} {
	                                        log_info $info "run dev/cmd order $order_no failed,test exited" 2;
        	                                set array_test($run_index,4) 0
                	                        append array_test($run_index,7) "order $order_no failed."
                                	        set result_value 1
	                                } else {
        	                                log_info $info "run dev/cmd order $order_no did not get in-line expect" 2;
                	                        if {$run_negate=="1"} {
                        	                        log_info $info "that's what test expected, test continue" 2;
                                	        	set result_value 0
                                	        } else {
                                        	        log_info $info "that's not what test expected, test exited" 2;
                                                	set array_test($run_index,4) 0
	                                                append array_test($run_index,7) "order $order_no failed. "
                                	        	set result_value 1
                                	        }
                                	}
                        	} else {
					log_info $info "run dev/cmd order $order_no successfully" 4
                                        if {$get_special_exp==0} {
						#wield case. need pay more attention
                                                log_info $info "***Attention***run dev/cmd order $order_no did not get in-line expect" 2;
                                                if {$run_negate=="1"} {
                                                        log_info $info "that's what test expected, test return 1" 2;
                                                	set result_value 0
                                                } else {
                                                        log_info $info "that's not what test expected, test exited" 2;
                                                        set array_test($run_index,4) 0
                                                        append array_test($run_index,7) "did not get in-line expect in dev/cmd order $order_no. "
                                                        #submit_res_and_log $run_index
                                                	set result_value 1
                                                }
                                        } else {
                                                log_info $info "run dev/cmd order $order_no got in-line expect" 2;
                                                if {$run_negate!="1"} {
                                                        log_info $info "that's what test expected, test return 1" 2;
                                                	set result_value 0
                                                } else {
                                                        log_info $info "negate value is $run_negate. that's not what test expected, test exited" 2;
                                                        set array_test($run_index,4) 0
                                                        append array_test($run_index,7) "got in-line expect but require negation in dev/cmd order $order_no."
                                                        #submit_res_and_log $run_index
                                                	set result_value 1
                                                }
                                        }
				}
                                if {$run_exit==1} {
                                        log_info $info "exit immediatelly" 5
        				exit_from_specified_dev $run_dev $spawn_id
                                }
				log_info $info "result_value: $result_value. 1 means fail, 0 means succeed" 2
				return $result_value
			} else {
				log_info $info "Request to use prev_connection, but device name is not the same. exit" 2
				return 1
			}
		} else {
  			if {[set run_spawn_id [run_comm_on_dev $run_dev $run_cmd_grp $run_exit]]==0} {
				#For run_exit=0 case, it only return spawn_id
				if {$get_special_exp==1} {
        	                       	log_info $info "run dev/cmd order $order_no failed,test exited" 2;
					set array_test($run_index,4) 0
					append array_test($run_index,7) "dev/cmd order $order_no failed. "
					#submit_res_and_log $run_index 
					return 1
				} else {
        	                       	log_info $info "run dev/cmd order $order_no did not get in-line expect" 2;
					if {$run_negate=="1"} {
						log_info $info "that's what test expected, test return 1" 2;
					} else { 
						log_info $info "that's not what test expected, test exited" 2;
						set array_test($run_index,4) 0
						append array_test($run_index,7) "did not get in-line expect in dev/cmd order $order_no. "
						#submit_res_and_log $run_index 
						return 1
					}
				}
                	} else {
				#If run_exit is 1, then connection should already been exit. so set run_spawn_id to 0 in \
				case later exit_process try to exit it again.
				if {$run_exit==1} { set run_spawn_id 0}
				log_info $info "run dev/cmd order $order_no on pre_src succeeded" 4;
			}
			#for the case which connection exit by itself because of running command
			if {$get_special_exp==0} {
				log_info $info "run dev/cmd order $order_no did not get in-line expect" 2;
                        	if {$run_negate=="1"} {
                                       	log_info $info "that's what test expected, test return 1" 2;
                                } else {
                                        log_info $info "that's not what test expected, test exited" 2;
                                        set array_test($run_index,4) 0
					append array_test($run_index,7) "did not get in-line expect in dev/cmd order $order_no. "
					#submit_res_and_log $run_index 
                                        return 1
                                }
			} else {
                        	log_info $info "run dev/cmd order $order_no got in-line expect" 2;
                                if {$run_negate!="1"} {
                                	log_info $info "that's what test expected, test return 1" 2;
                                } else {
                                        log_info $info "negate value is $run_negate. that's not what test expected, test exited" 2;
                                        set array_test($run_index,4) 0
                                        append array_test($run_index,7) "got in-line expect but require negation in dev/cmd order $order_no."
                                        #submit_res_and_log $run_index 
                                        return 1
                                }
			}
		}
	} else {
		log_info $info "cmd in dev/cmd order $order_no is blank or interrupt by user" 4
	}
	return 0
}

proc run_test {env} {
	#return 0 means test was interupted by error, all following testes should be stoped
	global db_handle TEST RUN_TEST_STATE RETRY_TIMES_WHEN_FAIL array_test test_no info map1 change_dut1 operator comm_array SLEEP_RUN interrupt get_special_exp \
	spawn_id spawn_id_array test_dev exit_when_test_fail DB_NAME
	set get_special_exp 1
	for {set i 1} {$i <= $test_no} {incr i +1} {
		log_info $info "array_test: $array_test($i,1), $array_test($i,2),$array_test($i,3). test_no: $test_no. i: $i" 6	
		set array_test($i,7) ""
		#array_test($i,2) means state, default value is coming from state field in env_test table. \
		State=0 means it won't be run by default, State=1 means run it, \
		state=2 means run it but do not care result, it means proc will not exit when it fail although exit_when_test_fail=1.
		set repeat [expr $RETRY_TIMES_WHEN_FAIL +1]
		while {$array_test($i,2)!=0 && $interrupt==0 && $repeat > 0} {
			log_info $info "Start to run test $array_test($i,1). May repeat [expr $repeat -1] times when fail" 2

			set sql_qur "SELECT * from $TEST where test_name='$array_test($i,1)' order by `order`"
                        set sky_response [mysql_pack $sql_qur $DB_NAME ]
                        set order_sum [lindex $sky_response 0]
                        set sql_ret_str [lindex $sky_response 1]
 
                        set k 0

			if {$order_sum >"0"} {
                        	log_info $info "Good, Found $order_sum test records in table $TEST!" 4

				for {set order_no 1} {$order_no<=$order_sum} {incr order_no +1} {
				        set cur_row [lindex $sql_ret_str $k]
                                        incr k +1
			                set test_name($order_no) [lindex $cur_row 1]
			                set test_desc($order_no) [lindex $cur_row 2]
			                set test_type($order_no) [lindex $cur_row 3]
		        	        set test_cmd($order_no) [string trim [lindex $cur_row 4]]
		                	set test_dev($order_no) [lindex $cur_row 5]
		                	set test_negate($order_no) [lindex $cur_row 6]
		                	set test_sleep($order_no) [lindex $cur_row 7]
		                	set test_round_times($order_no) [lindex $cur_row 8]
		                	set test_belong_group($order_no) [lindex $cur_row 9]
		                	set test_state($order_no) [lindex $cur_row 10]
		                	set test_exit_after_cmd($order_no) [lindex $cur_row 11]
		                	set test_order($order_no) [lindex $cur_row 12]
		                	set test_new_conn($order_no) [lindex $cur_row 13]
		                	set test_prev_conn($order_no) [lindex $cur_row 14]
		                	set test_in_round($order_no) [lindex $cur_row 15]
		                	set test_stop_test($order_no) [lindex $cur_row 16]
		                	set test_owner($order_no) [lindex $cur_row 17]
				}
				#Check current RUN_TEST_STATE to see if we need run this test
				if {[string last $test_state(1) $RUN_TEST_STATE ] != "-1" }  {
				        #start to run test
        				switch $test_type(1) {
        				ping 	{
					        #run pre_cmd on pre_src
        	                                if {$test_pre_cmd!=""} {
                	                                if {[run_comm_on_dev $test_pre_src $test_pre_cmd $test_exit_after_pre_cmd]!=1} {
                        	                                log_info $info "run pre_cmd on pre_src failed" 2;
                                	                        return 0
                                        	        }
        	                                }
        
        					set conn_succ [connect_setup  $src_ip $src_user $src_pass $src_mode $src_port]
        					if {$conn_succ==1} {
        						set array_test($i,4) [pingtest $dst_ip]
                	                                if {$array_test($i,4)==1} {
                        	                                log_info $info  "got expect result, ping test $test_name succeeded!" 3
                                	                        set array_test($i,4) 1
                                        	        } else {
                                                	        log_info $info  "didnot get expect result, ping test $test_name failed!" 2
                                                        	set array_test($i,4) 0
        						}
        						exit_from_dev $src_port $src_mode	
                                                }
        					
        					}
        				h323ohphone {
        					set spawn_id_pre_cmd 0
                                                if {$test_pre_cmd!=""} {
                                                        if {[set spawn_id_pre_cmd [run_comm_on_dev $test_pre_src $test_pre_cmd \
							$test_exit_after_pre_cmd]]==0} {
                                                                log_info $info "run pre_cmd on pre_src failed" 2;
                                                                set array_test($i,4) 0
                                                                set array_test($i,6) 0
                                                                set array_test($i,7) "run pre_cmd on pre_src failed"
                                                                submit_res $i
                                                        }
                                                }
                                                log_info $info "I'm sleeping for $test_sleep seconds" 2
                                                sleep $test_sleep
        	                                if {[get_access $test_dst dst_ip dst_mode dst_user dst_pass dst_port]==0} {
                	                                set array_test($i,4) 0
                        	                        continue
                                	        }
                                                set spawn_id_test_src [connect_setup  $src_ip $src_user $src_pass $src_mode $src_port]
                                                set spawn_id_test_dst [connect_setup  $dst_ip $dst_user $dst_pass $dst_mode $dst_port]
        					if {$spawn_id_test_src != 0 && $spawn_id_test_dst != 0 && $interrupt==0} {
        						set test_cmd [trimend $test_cmd "\n\r"]
        						foreach sub_test_case [lindex [split $test_cmd "\n"] {
        							if {[regexp (.*)!!!(.*) $sub_test_case no_use sub_cmd_for_src sub_cmd_for_dst]==1} {
        								set sub_cmd_for_src "/env_test/ohphone -u $test_src -g $test_exp_resu -a \
									-$sub_cmd_for_src $test_dst"
        								set sub_cmd_for_dst "/env_test/ohphone -u $test_dst -g $test_exp_resu -la \
									-$sub_cmd_for_dst"
        								set spawn_id $spawn_id_test_dst
        								run_comm_exp_res $sub_cmd_for_dst "Command"
        								set spawn_id $spawn_id_test_src
        								run_comm_exp_res $sub_cmd_for_dst "established"
        								set reg_exp ""
        							}
        						}
        					}
        					}
        				check   {
        					set spawn_id_value ""
        					set array_test($i,4) 1
        					set cont_cur_round 1
        					for {set order_no 1} {$order_no<=$order_sum} {incr order_no +1} {
        						if {[set cont_value [process_cmd_on_dev $i $order_no $test_dev($order_no) $test_cmd($order_no) \
							spawn_id_value $test_exit_after_cmd($order_no) $test_negate($order_no) \
							$test_new_conn($order_no) $test_prev_conn($order_no) ]]==1} { 
								
        							set spawn_id_array($order_no) $spawn_id_value
								log_info $info "2:cmd fail! $test_stop_test($order_no) " 2
                                                                        set spawn_id_array($order_no) $spawn_id_value
                                                                        switch $test_stop_test($order_no) {
                                                                        1 {set array_test($i,4) 0; break}
                                                                        2 {set array_test($i,4) 0;set cont_cur_round 0;continue}
                                                                        3 {}
                                                                        default {log_info $info "unknown stop_test value:$test_stop_test($order_no). \
									continue test." 2}
                                                                        }
        						} else {
								log_info $info "2:cmd succeed! $test_stop_test($order_no) " 2
        							log_info $info "Run dev/cmd of order $order_no successfully" 3
        							log_info $info "Sleep for $test_sleep($order_no) seconds" 3
        							log_info $info "Spawn_id_value: $spawn_id_value" 4
        							sleep $test_sleep($order_no)
        							set spawn_id_array($order_no) $spawn_id_value
        						}
        						if {$interrupt==1} {return 0}
        					}
        					if {$interrupt==1} {return 0}
        					#submit result and exit connection	
        					set test_pass [submit_res_and_log $i]
        					exit_from_all_dev $order_sum 
        
        					#Adding below lines is for some special test cases which may fail occassionally
        					if {$test_pass=="0"} {
        						incr repeat -1
        						append array_test($i,7) "***Try again***"
        					} else {
        						set repeat 0
        					}
                                                if {$exit_when_test_fail=="1" && $test_pass=="0" && $repeat == "0" && $array_test($i,2)!="2"} {
                                                        return 0
                                                } else {
                                                        continue
                                                }
        					}
        				r_check {
        					set spawn_id_value ""
        					set array_test($i,4) 1
        					set array_test($i,6) 0
        					set cont_cur_round 1
        
        					set run_times 0
        					while {$interrupt==0 && $cont_cur_round==1 && $array_test($i,4)==1 && $run_times < $test_round_times(1)} {
        						incr run_times +1
        						log_info $info "run test $test_name(1) in the $run_times/$test_round_times(1) times" 3
        	                                        for {set order_no 1} {$order_no<=$order_sum} {incr order_no +1} {
        							###If not in_round, then skip running
        							if {$test_in_round($order_no)==0} {continue}
                	                                        if {[set cont_value [process_cmd_on_dev $i $order_no $test_dev($order_no) \
								$test_cmd($order_no) spawn_id_value $test_exit_after_cmd($order_no) \
								$test_negate($order_no) $test_new_conn($order_no) $test_prev_conn($order_no) ]]==1} {
                                                                	set spawn_id_array($order_no) $spawn_id_value
        								switch $test_stop_test($order_no) {
        								"1" {log_info $info "stop_test is 1. exit immediately" 2; \
										set array_test($i,4) 0; break}
        								"2" {log_info $info "stop_test is 2. finish this round and then exit" 3; \
										set array_test($i,4) 0;set cont_cur_round 0;continue}
        								"3" {log_info $info "stop_test is 3. run continully" 3;}
        								default {log_info $info "unknown stop_test value:$test_stop_test($order_no). \ 
										continue test." 2}
        								}
                                	                        } else {
                                        	                        log_info $info "Run dev/cmd of order $order_no successfully" 3
        	                                                        log_info $info "Sleep for $test_sleep($order_no) seconds" 3
                	                                                log_info $info "Spawn_id_value: $spawn_id_value" 4
                        	                                        sleep $test_sleep($order_no)
                                	                                set spawn_id_array($order_no) $spawn_id_value
                                        	                }
        							if {$interrupt==1} {return 0}
                                                	}
                                                	exit_from_all_dev $order_sum
        					}
                                                #submit result and exit connection
                                                set test_pass [submit_res_and_log $i]
                                                exit_from_all_dev $order_sum
        
                                                #Adding below lines is for some special test cases which may fail occassionally
                                                if {$test_pass=="0"} {
                                                        incr repeat -1
        						append array_test($i,7) "***Try again***"
                                                } else {
                                                        set repeat 0
                                                }
        
        					if {$exit_when_test_fail=="1" && $test_pass=="0" && $repeat == "0" && $array_test($i,2)!="2"} {
        						return 0
        					} else {
                                                	continue
        					}
        					}
        				default {
						log_info $info "unsupported test_type: $test_type(1)" 2
						set repeat 0
						continue
						}
        				}
        				log_info $info "Finish test $array_test($i,1)" 2
				} else {
					log_info $info "test state is $test_state(1) which is not in current run_state list:$RUN_TEST_STATE" 2
                                        set repeat 0
					continue
				}
			} else {
                        	log_info $info "Cannot found test_name $array_test($i,1) in DB! Cancel the test" 2
				set array_test($i,4) 0
				set repeat 0
				continue
			}
		}
	}
}
proc show_map {} {
	global map1 info
	log_info $info "enter show_map" 2
	set i 1
	while {[info exists map1($i,1)] && [info exists map1($i,2)]} {
		log_info $info "map1($i,1): $map1($i,1); map1($i,2): $map1($i,2)" 2
		incr i +1
	}
}
proc set_map {env_dut env_dut_new env_options env_options_new} {
	global map1 info
	catch {unset map1}
        set map1(1,1) $env_dut
        set map1(1,2) $env_dut_new
        set i 2
        #foreach map [split $env_options] 
        foreach map $env_options {
        	set map1($i,1) $map
		log_info $info "map1($i,1):$map1($i,1)" 6
                incr i +1
        }
	set j $i
        set i 2
        #foreach map [split $env_options_new] 
        foreach map $env_options_new {
        	set map1($i,2) $map
		log_info $info "map1($i,2):$map1($i,2)" 6
                incr i +1
        }
	if {$j!=$i} {
		return 0
	} else {
		return 1
	}
}
proc set_map_other {index env_dut env_dut_new env_options env_options_new} {
	global map_other info
        log_info $info "env_options: $env_options" 5
        log_info $info "env_options_new: $env_options_new" 5
	#####setup mapping in map_other for item "index". if index is 0, then create a new mapping item
	#####return 0 means mapping failure, if succeed, return the using index number. 
	#for multiple mapping, donot need unset it
	#unset map_other
	#setup index to next available number in map_other
	if {$index == 0} {
		set index 1
		while {[info exists map_other($index,1,1)]} {
			if {$map_other($index,1,1)==$env_dut} {
				log_info $info "found exist mapping for dev:$env_dut, try to append mapping" 2
				if {$map_other($index,1,2)== $env_dut_new} {
					break
				} else {
					###mapping destination is different. Now we need check if now we should map it to another destination
				        if {$env_dut==$env_dut_new} {	
						###First time, test_src was mapped to PC6, Second time, test_src was mapped to test_src itself, 
						###but changed some content. We should consider it as mapped to old_dst(PC6), just append mapping.
						log_info $info "mapping destination is different, and new mapping does not change device, append mapping" 2
						set env_dut_new $map_other($index,1,2)
						break
						#
					} else {
						###we should destory old mapping
						log_info $info "mapping destination is different, destroy old mapping, create new mapping" 2
						set ii 2
						while {[info exists map_other($index,$ii,1)]} {
							unset map_other($index,$ii,1)
							unset map_other($index,$ii,2)
							incr ii +1
						}
						break
					}
				}
			}
			incr index +1
		}
	}
        set map_other($index,1,1) $env_dut
        set map_other($index,1,2) $env_dut_new
	log_info $info "map_other($index,1,1): $map_other($index,1,1);map_other($index,1,2): $map_other($index,1,2)" 5
        set i 2

        foreach map $env_options {
		if {$map!=""} {	
			set map_susp($i,1) $map
			incr i +1
		}
	}
	set j $i
        set i 2
        foreach map $env_options_new {
                if {$map!=""} {
        		#Workaround the case which map is a list
			set map111 [string map "\\\\\\\\ \\\\" $map]
        		log_info $info "map111: $map111" 5
                        set map_susp($i,2) $map111
                        incr i +1
                }
        }
        if {$j!=$i} {
		log_info $info "mapping options does not match for $env_dut" 3
                return 0
        }
	for {set i 2} {$i<$j} {incr i +1} {
		set ii 2
		###If found same mapping item, then overwrite it
		while {[info exists map_other($index,$ii,1)]} {
			if {$map_other($index,$ii,1)==$map_susp($i,1)} {
				log_info $info "found exist mapping item for $map in dev $env_dut, overwrite it" 2
				break
			} 
			incr ii +1
		}
		set map_other($index,$ii,1) $map_susp($i,1)
		set map_other($index,$ii,2) $map_susp($i,2)
		log_info $info "map_other($index,$ii,1): $map_other($index,$ii,1); map_other($index,$ii,2): $map_other($index,$ii,2)" 5
        }
	if {$map_other($index,$ii,1)==$map_other($index,$ii,2) && $map_other($index,$ii,1)=="reset_it"} {
	#Reset all mapping for the device
		set ii 2
		while {[info exists map_other($index,$ii,1)]} {
			unset map_other($index,$ii,1)
			unset map_other($index,$ii,2)
			incr ii +1
		}
	}
	return $index
}
proc show_map_other_all {} {
	global map_other info
        log_info $info "enter show_map_other" 2
	set i 1
	while {[info exists map_other($i,1,1)]} {
		show_map_other $i
		incr i +1
	}
}
proc show_map_other {index} {
        global map_other info
        log_info $info "enter show_map_other for index: $index" 2
        set i 1
        while {[info exists map_other($index,$i,1)]} {
                log_info $info "map_other($index,$i,1): $map_other($index,$i,1); map_other($index,$i,2): $map_other($index,$i,2)" 2
                incr i +1
        }
}

proc input_dut_to_db {} {
	global change_dut1 map1 ENV_DUT DB_NAME info env_dut env_options env_dut_new env_options_new root_env cmd_win
        set map1(1,1) $env_dut
        set map1(1,2) $env_dut_new
	log_info $info "$root_env, $env_dut,$env_options,$env_dut_new, $env_options_new" 6
# input date into db
        set sql_qur "SELECT * from $ENV_DUT where env_name='$root_env'"
        set sky_response [mysql_pack $sql_qur $DB_NAME ]
        set parent_line [lindex $sky_response 0]
        set sql_ret_str [lindex $sky_response 1]

        set k 0



        if {$parent_line >"0"} {
                log_info $info "Found $parent_line device records in $ENV_DUT DB! " 2
                set sql_qur "UPDATE $ENV_DUT SET dut_name='$map1(1,1)' ,options='$env_options', dut_changeto='$env_dut_new', options_changeto='$env_options_new' WHERE env_name='$root_env'"
                set sky_response [mysql_pack $sql_qur $DB_NAME ]
                set infect_line [lindex $sky_response 0]
                set sql_ret_str [lindex $sky_response 1]

                set k 0

                if {$infect_line =="1"} {
                        log_info $info "UPDATE value successfully! env_name: $root_env, dut_name: $map1(1,1), options: $env_options" 2
                } else {
                        log_info $info "Fail to update database $ENV_DUT !\n" 1
                        log_info $info "infect line: $infect_line \n . should be 1 " 1
                }
	} else {
		set sql_qur "INSERT INTO $ENV_DUT values('','$root_env','$env_dut','$env_options','$env_dut_new','$env_options_new')"
                set sky_response [mysql_pack $sql_qur $DB_NAME ]
                set infect_line [lindex $sky_response 0]
                set sql_ret_str [lindex $sky_response 1]

                set k 0

	        if {$infect_line =="1"} {
        	        log_info $info "Insert Into database $ENV_DUT successfully!" 3
	        } else {
        	        log_info $info "Fail to insert into database !" 2
        	}
	}
# Create map
	if {$env_dut_new!=""} {
		set mapping_result [set_map $env_dut $env_dut_new $env_options $env_options_new]
		if {$mapping_result==0} {
			log_info $info "mapping failure, return without mapping" 2
			return 0
		}
	}
	set w1 .change_DUT_prove
        catch {destroy $w1}
        toplevel $w1
        wm title $w1 "Confirmation for changing DUT"
        wm iconname $w1 "iconname?"
        positionWindow $w1
	label $w1.1 -text "DUT change from $map1(1,1) to $map1(1,2)" -padx 0 -width 20 -anchor e
	pack $w1.1 -side top -fill x -pady 2m -expand 1
	for {set k 2} {$k<$i} {incr k +1} {
		label $w1.$k -text "port change from $map1($k,1) to $map1($k,2)" -padx 0 -width 20 -anchor e
		pack $w1.$k -side top -fill x -pady 2m -expand 1
	}
        button $w1.confirm -text Confirm -command " 
		set change_dut1 1;  
		catch {destroy $w1};
		set_disable_chg_dut; 
		return 1 "
        button $w1.cancel -text Cancel -command " catch {destroy $w1} ; return 0 "
	pack $w1.confirm -side bottom -fill x -pady 2m -expand 1
	pack $w1.cancel -side right -fill x -pady 2m -expand 1

}
proc set_disable_chg_dut {} {
	global cmd_win
	$cmd_win.set_dut configure -text "Disable Change DUT"
}

proc check_crash {dev_name} {
	global cmd_check_crash
	if {[set result [run_comm_on_dev $dev_name $cmd_check_crash 1]]!=0} {
		return 1
	}
	return 0
}

proc check_backlog {dev_name} {
        global cmd_check_backlog
        if {[set result [run_comm_on_dev $dev_name $cmd_check_backlog 1]]!=0} {
                return 1
        }
	return 0
}

proc check_status {} {
	#return 0 means no problem found, return 1 means found some problem
	global array1 info DEV_TB DB_NAME interrupt DB_PRV_NAME
        set i 1
	set crash_log 0
	set enter_backlog 0
	set nouse ""
        while { [info exists array1($i,1)] } {
		set dev $array1($i,1)
	        map_dev_cmd dev nouse
		log_info $info "$array1($i,1) mapped to $dev, go to check $dev status" 4
                set sql_qur "SELECT type from $DEV_TB where name='$dev'"
                set sky_response [mysql_pack $sql_qur $DB_PRV_NAME ]
                set rows_num [lindex $sky_response 0]
                set sql_ret_str [lindex $sky_response 1]

                set k 0

		log_info $info "sql_qur: $sql_qur" 5
		log_info $info "interrupt $interrupt" 6
                if {$rows_num!=0 && $interrupt!=1} {
                        set device_type  [lindex $sql_ret_str 0]
			log_info $info "device_type is $device_type" 5
#			set device_type [string toupper [string range [trimfirst $array1($i,1)] 0 1]] 
			if {$device_type=="FortiOS"} {
				set crash_log 0
				set enter_backlog 0
				set crash_log [check_crash $array1($i,1)]
				set enter_backlog [check_backlog $array1($i,1)]
				if {$crash_log==1 || $enter_backlog==1} {
					log_info $info "crash or enter backlog in $array1($i,1)! " 2
					return 1
				} else {
					log_info $info "status is ok in $array1($i,1)" 3
				}
			} else {
				log_info $info "non-FortiOS type donot need to check" 5
			}
		} else {
			log_info $info "Cannot find device $array1($i,1) or system interrupted manually" 2
		}
		incr i +1
	}
	return 0
}
proc change_dut {} {
        global info cur_env ENV_DUT DB_NAME env_dut env_options env_dut_new env_options_new root_env change_dut1 cmd_win interrupt running_pid
        if {$change_dut1==0} {
                set w .change_DUT
                catch {destroy $w}
                toplevel $w
                wm title $w "Set and Change DUT for this ENV"
                wm iconname $w "iconname?"
                positionWindow $w
        
                frame $w.left
                frame $w.right1
        	frame $w.right2
                frame $w.command
                pack $w.left $w.right1 $w.right2 -side left -expand yes -padx 10 -pady 10 -fill both
                pack $w.command -side bottom  -fill x -pady 2m
        	# check database to get original value
        	if {[string first / $cur_env]==-1} {
        		set root_env $cur_env
        	} else { 
        		set root_env [string range $cur_env 0 [expr [string first / $cur_env]-1]] 
        	}
        	log_info $info "root_env: $root_env ; cur_env: $cur_env" 6
                set sql_qur "SELECT * from $ENV_DUT where env_name='$root_env'"

                set sky_response [mysql_pack $sql_qur $DB_NAME ]
                set parent_line [lindex $sky_response 0]
                set sql_ret_str [lindex $sky_response 1]

                set k 0

        	set env_dut ""
        	set env_options ""
        	set env_dut_new ""
        	set env_options_new ""
               	if {$parent_line >"0"} {
                	log_info $info "Good, Found $parent_line device records in table $ENV_DUT! only handle the first one" 4
                        set cur_row [lindex $sql_ret_str 0]
                        set env_dut [lindex $cur_row 2]
                        set env_options [lindex $cur_row 3]
                        set env_dut_new [lindex $cur_row 4]
                        set env_options_new [lindex $cur_row 5]
        	}
                label $w.left.env_name -text "Env name:" -padx 0 -width 20 -anchor e
                label $w.left.dut_name -text "DUT name:" -padx 0 -width 20 -anchor e
                label $w.left.options -text "Ports in test:" -padx 0 -width 30 -anchor e
        
                label $w.right1.env_name -text "Original" -padx 0 -width 20 -anchor e
                entry $w.right1.env_dut -width 30 -relief sunken -textvariable env_dut
                entry $w.right1.env_options -width 30 -relief sunken -textvariable env_options
        
                label $w.right2.env_name -text "Change to" -padx 0 -width 20 -anchor e
                entry $w.right2.env_dut -width 30 -relief sunken -textvariable env_dut_new
                entry $w.right2.env_options -width 30 -relief sunken -textvariable env_options_new
        
                button $w.command.confirm -text Confirm -command " \
        		puts $env_dut;puts $env_options;
        		input_dut_to_db ; \
        		catch {destroy $w} "
                button $w.command.cancel -text Cancel -command " catch {destroy $w} ; return 0 "
                pack $w.left.env_name $w.left.dut_name $w.left.options -side top -expand yes -pady 2 -anchor e
                pack $w.right1.env_name $w.right1.env_dut $w.right1.env_options -side top -expand yes -pady 2 -anchor w
                pack $w.right2.env_name $w.right2.env_dut $w.right2.env_options -side top -expand yes -pady 2 -anchor w
                pack $w.command.confirm $w.command.cancel -side top -expand 1
         } else {
		show_map
		show_map_other_all
		log_info $info "interrupt value: $interrupt" 2
		log_info $info "running pid: $running_pid" 2
                after idle {.dialog1.msg configure -wraplength 4i}
                set i [tk_dialog .dialog1 "Disable Changing DUT" " You selected to disable changing DUT, that means \
		substitution will stop in following config and test, Are you sure?" info 0 OK Cancel]
                switch $i {
                    0 {
                       set change_dut1 0
                       .f.out_window.cmd.set_dut configure -text "Change DUT"
                       log_info $info "Disable Change DUT" 2
                      }
                    1 {log_info $info "Cancel disabling Changing DUT" 2}
                }
         }
}
proc conf_run_env {cur_env} {
	global info db_handle TREE_TB sf_dev_list sf_test_list SLEEP_RUN dev_no test_no interrupt SLEEP_AFTER_CONF exit_when_found_problem parent_env_for_pkg

  	.f.out_window.l config -text "current env: $cur_env"
	if {$interrupt!=1} {
		set old_env $cur_env
		log_info $info "Conf_run_env:Start to run and test env:$cur_env" 2
        	log_info $info "cur_env: $cur_env" 2
		#####Start to handle cur_env
		list_dev_for_env $sf_dev_list $cur_env
		list_test_for_env $sf_test_list $cur_env
		if {$dev_no>0 && $interrupt!=1} {
			log_info $info "***Start to config $cur_env!***  " 4
			if {$interrupt==1} {log_info $info "system interrupted after list dev&test for env: $cur_env" 2; return 0} 
			set SLEEP_RUN 0
			run_env $cur_env
			#for system is booting up or some other case, auto_run need sleep for a while
			sleep $SLEEP_RUN
			set SLEEP_RUN 0
			if {$test_no>0} {
				log_info $info "finished to config $cur_env! Sleep for $SLEEP_AFTER_CONF seconds, test is coming. " 2
				sleep $SLEEP_AFTER_CONF
				log_info $info "***Start to test $cur_env!*** " 2
				if {$interrupt==1} {log_info $info "system interrupted after config dev for env: $cur_env" 2; return 0} 
				if {[run_test $cur_env]==0} {
					log_info $info "test failed and paused by exit_when_test_fail==1" 2
					pause_running
#					set interrupt 1
#					return 0
				} else {
					log_info $info "finished all tests in env:$cur_env " 2
				}
			} else {
				log_info $info "*** no test item in this env, skip test***" 3
			}
			#Add below proc to check current status in device which is in array1: crashlog, etc
			if {$exit_when_found_problem} {
				log_info $info "exit_when_found_problem is 1, go to check if devices as OK!" 3
        			set found_problem 0
        			set found_problem [check_status]
        			if {$exit_when_found_problem && $found_problem} {
        				log_info $info "Found problem and exit_when_found_problem is true, pause!" 2
					pause_running
#        				set interrupt 1
#        				return 0
        			} 
			}
		} else {
			log_info $info "***no device in this env or system interrupted, skip config and test***" 2
		}
                #####Add checking if cur_env is a package
	        set son_env [get_son_env $cur_env]
        	set parent_env [get_parent_env $cur_env]
	        log_info $info "cur_env: $cur_env; son_env: $son_env; parent_env: $parent_env " 4

                set sql_qur "SELECT state from $TREE_TB where ParentID='$parent_env' and name='$son_env'"
                set sky_response [mysql_pack $sql_qur $DB_NAME ]
                set rows_num [lindex $sky_response 0]
                set sql_ret_str [lindex $sky_response 1]

                set k 0

                log_info $info "sql_qur: $sql_qur" 5
                if {$rows_num!=0 && $interrupt!=1} {
                        set cur_state [lindex $sql_ret_str 0]
                        if {[string trim $cur_state]=="5"} {
				append parent_env_for_pkg $parent_env
				log_info $info "parent_env_for_pkg1: $parent_env_for_pkg; parent_env: $parent_env" 3
                                conf_run_env_all $son_env
				log_info $info "parent_env_for_pkg2: $parent_env_for_pkg; parent_env: $parent_env" 3
				set parent_env_for_pkg [trimend $parent_env_for_pkg $parent_env]
				log_info $info "parent_env_for_pkg3: $parent_env_for_pkg; parent_env: $parent_env" 3
                                return 1
                        } else {
                                #do nothing if that is a normal env
                        }
                } else {
                        log_info $info "cannot find cur_env in database table $TREE_TB, exit!" 2
                        return 0
                }
                #####Finish Checking package
	} else {
		log_info $info " system interrupted before config&run env: $cur_env" 2
		return 0
	}
}
proc conf_run_env_all_old {env_value} {
	global info DB_NAME sf_dev_list sf_test_list TREE_TB SLEEP_RUN interrupt
	set old_env $env_value
	set cur_env $env_value
	log_info $info "*******************************************************" 2
	log_info $info "*start to config and run all test in below env:" 2
	log_info $info "*conf_run_env_all: $cur_env" 2
	log_info $info "*******************************************************" 2
        set son_env [get_son_env $cur_env]
        set parent_env [get_parent_env $cur_env]
	log_info $info "cur_env: $cur_env; son_env: $son_env; parent_env: $parent_env " 2

	if {$parent_env!="0"} {
		set run_env "$parent_env/$son_env"
	} else {
		set run_env $son_env
	}
	log_info $info "run_env: $run_env" 2
	conf_run_env $cur_env 

        #Add below lines to run 'rm_all' when entering a sub_directory first time
        set sql_qur "SELECT * from $TREE_TB where ParentID='$run_env' and Name='rm_all'"
        set sky_response [mysql_pack $sql_qur $DB_NAME ]
        set exist_rm_all [lindex $sky_response 0]
        set sql_ret_str [lindex $sky_response 1]
        set k 0

        log_info $info "handle rm_all first: $sql_qur" 2
        if {$exist_rm_all!=0 && $interrupt!=1} {
                set cur_env "$run_env/rm_all"
                log_info $info "now run rm_all: $cur_env" 2
                conf_run_env_all $cur_env
        } else {
            log_info $info "no rm_all for $run_env exist" 2
        }

        #Add name!='rm_all' at Aug 16,2006. Because we always have special code for rm_all
	set sql_qur "SELECT name,state,run_times from $TREE_TB where ParentID='$run_env' and name!='rm_all' ORDER BY Parentid, name"
        set sky_response [mysql_pack $sql_qur $DB_NAME ]
        set rows_num [lindex $sky_response 0]
        set sql_ret_str [lindex $sky_response 1]
        set k 0

        if {$rows_num!=0 && $interrupt!=1} {
	    set i 1
            while {[set cur_row [lindex $sql_ret_str 0]]!=""} {
                set row(1) [lindex $cur_row 0]
                set row(2) [lindex $cur_row 1]
                set row(3) [lindex $cur_row 2]
		set env_group($i,1) "$run_env/$row(1)"
		set env_group($i,2) "$run_env/rm_all"
		#state
		set env_group($i,3) "$row(2)"
		#run_times
		set env_group($i,4) "$row(3)"

		log_info $info "run_env: $run_env; row(1): $row(1); row(2):$row(2); row(3):$row(3) " 5
		log_info $info "env_group($i,1): $env_group($i,1); env_group($i,2): $env_group($i,2); " 5
		incr i +1
            }
#Move below lines to outside of this if-loop, then rm_all will also be run if there is not other sub-env in same level
#            #Add below lines to run 'rm_all' when entering a sub_directory first time
#            set SQL_stat "SELECT * from $TREE_TB where ParentID='$run_env' and Name='rm_all'"
#            log_info $info "handle rm_all first: $SQL_stat" 2
#            set exist_rm_all [::mysql::sel $db_handle $SQL_stat]
#            if {$exist_rm_all!=0 && $interrupt!=1} {
#                    set cur_env "$run_env/rm_all"
#                    log_info $info "now run rm_all: $cur_env" 2
#                    conf_run_env $cur_env
#            } else {
#		log_info $info "no rm_all for $run_env exist" 2
#	    }

	    for {set j 1} {$j<$i} {incr j +1} {
		if {$interrupt!=1} {
			log_info $info "now run env: $env_group($j,1)" 2
        	        set cur_env $env_group($j,1)
			if {$env_group($j,3)!="0"} {
				for {set times 1} {$times<=$env_group($j,4)} {incr times +1} {
					log_info $info "run $env_group($j,1) in the $times/$env_group($j,4) times" 2
		                	conf_run_env_all $env_group($j,1)
					if {$interrupt!=1} {
                        			#Add below lines to run 'rm_all'
                                                set sql_qur "SELECT * from $TREE_TB where ParentID='$run_env' and Name='rm_all'"
                                                set sky_response [mysql_pack $sql_qur $DB_NAME ]
                                                set exist_rm_all [lindex $sky_response 0]
                                                set sql_ret_str [lindex $sky_response 1]
                                                set k 0

                        			log_info $info "handle rm_all after(should be same as first): $sql_qur" 2
                                                #set exist_rm_all [::mysql::sel $db_handle $SQL_stat]
                        	                if {$exist_rm_all!=0} {
                                	                set cur_env $env_group($j,2)
                                        	        log_info $info "now run rm_all: $env_group($j,2)" 2
                        				conf_run_env $cur_env
                        			} else {
                        		                log_info $info "no rm_all for $run_env exist" 2
                        	                }
					} else {
						log_info $info "system interrupted,don't need to run rm_all under $cur_env" 3
						return 0
					}
                                }
                        } else {
				log_info $info "state of env $env_group($j,1) is 0, ignore it" 2
			}
		}
	    }
	} else {
		log_info $info "system interrupted or no other sub_env under $cur_env need to be config and test" 3
	}
	set cur_env $old_env
	log_info $info "********************************************************************" 2
	log_info $info "*finish to config and run all test in $cur_env" 2
	log_info $info "********************************************************************" 2
}

proc conf_run_env_all {env_value} {
	global info DB_NAME sf_dev_list sf_test_list TREE_TB SLEEP_RUN interrupt cur_env
	set old_env $env_value
	set cur_env $env_value
	log_info $info "*******************************************************" 2
	log_info $info "*start to config and run all test in below env:" 2
	log_info $info "*conf_run_env_all: $cur_env" 2
	log_info $info "*******************************************************" 2
        set son_env [get_son_env $cur_env]
        set parent_env [get_parent_env $cur_env]
	log_info $info "cur_env: $cur_env; son_env: $son_env; parent_env: $parent_env " 2

	if {$parent_env!="0"} {
		set run_env "$parent_env/$son_env"
	} else {
		set run_env $son_env
	}
	log_info $info "run_env: $run_env" 2
	conf_run_env $cur_env 

	set sql_qur "SELECT name,state,run_times from $TREE_TB where ParentID='$run_env' ORDER BY Parentid, name"
        set sky_response [mysql_pack $sql_qur $DB_NAME ]
        set rows_num [lindex $sky_response 0]
        set sql_ret_str [lindex $sky_response 1]
        set k 0

        if {$rows_num!=0 && $interrupt!=1} {
	    set i 1
            while {[set cur_row [lindex $sql_ret_str $k]]!=""} {
                incr k +1
                set row(1) [lindex $cur_row 0]
                set row(2) [lindex $cur_row 1]
                set row(3) [lindex $cur_row 2]
		set env_group($i,1) "$run_env/$row(1)"
		set env_group($i,2) "$run_env/rm_all"
		#state
		set env_group($i,3) "$row(2)"
		#run_times
		set env_group($i,4) "$row(3)"

		log_info $info "run_env: $run_env; row(1): $row(1); row(2):$row(2); row(3):$row(3) " 5
		log_info $info "env_group($i,1): $env_group($i,1); env_group($i,2): $env_group($i,2); " 5
		incr i +1
            }
	    for {set j 1} {$j<$i} {incr j +1} {
		if {$interrupt!=1} {
		    if {($env_group($j,1)==$env_group($j,2) && $i==2) || ($env_group($j,1) != $env_group($j,2))} {
			log_info $info "now run env: $env_group($j,1)" 2
			if {$env_group($j,3)!="0"} {
				for {set times 1} {$times<=$env_group($j,4)} {incr times +1} {
					log_info $info "run $env_group($j,1) in the $times/$env_group($j,4) times" 2
		                	conf_run_env_all $env_group($j,2)
					if {$env_group($j,1)!=$env_group($j,2)} {
			                	conf_run_env_all $env_group($j,1)
					}
                                }
                        } else {
				log_info $info "state of env $env_group($j,1) is 0, ignore it" 2
			}
		    }
		}
	    }
	    set j [expr $j-1]
	    if {$env_group($j,1)!=$env_group($j,2)} {
  	        conf_run_env_all $env_group($j,2)
	    }
	} else {
		log_info $info "system interrupted or no other sub_env under $run_env need to be config and test" 3
	}
	log_info $info "********************************************************************" 2
	log_info $info "*finish to config and run all test in $cur_env" 2
	log_info $info "********************************************************************" 2
}
